﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Linq;
using System.Reflection;
using ZOIL.DataModel;

namespace ZOIL.DataBackend
{
    public class DataBackendSelection
    {
        #region Composition

        private readonly CompositionContainer _container;

        [ImportMany(typeof(CollectionConnectionBase))]
        public List<CollectionConnectionBase> Connections { get; set; }

        public CollectionConnectionBase ActiveConnection { get; private set; }

        #endregion

        #region Singleton Instance

        private static DataBackendSelection _instance;
        public static DataBackendSelection Instance
        {
            get { return _instance ?? (_instance = new DataBackendSelection()); }
        }

        #endregion

        private DataBackendSelection()
        {
            var catalog = new AggregateCatalog();

            catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetEntryAssembly()));

            // Check for data backend impl directory and containing assemblies.
            var fullPath = Assembly.GetExecutingAssembly().Location;

            var binaryDirectory = Directory.GetParent(fullPath).FullName;
            catalog.Catalogs.Add(new DirectoryCatalog(binaryDirectory, "ZOIL.DataBackend.*.dll"));

            var backendImplDirectory = Path.Combine(binaryDirectory, "DataBackendImpl");
            if (Directory.Exists(backendImplDirectory))
                catalog.Catalogs.Add(new DirectoryCatalog(backendImplDirectory, "ZOIL.DataBackend.*.dll"));

            _container = new CompositionContainer(catalog);

            _container.ComposeParts(this);

            if (Connections.Count == 0)
            {
                ActiveConnection = new LocalOnlyCollectionConnection();
            }
            else if (Connections.Count == 1)
            {
                ActiveConnection = Connections.First();
            }
            else if (Connections.Count > 1)
            {
                var dialog = new DataBackendChooser { DataContext = this };

                var result = dialog.ShowDialog();

                if (result.HasValue && !result.Value)
                    throw new Exception("No data backend has been selected");

                ActiveConnection = dialog.DatabaseConnection;
                CollectionFactoryProvider.Factory = ActiveConnection;
            }
        }

        public static IPersistableCollection Instance2
        {
            get
            {
                var coll = DatabaseCollection.Collection;
                if (coll == null)
                {
                    throw new InvalidOperationException("No Collection set!");
                }
                return coll;
            }
        }
    }
}